package com.lp.service.controller;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.iframework.commons.util.fast.L;
import org.iframework.commons.util.fast.V;
import org.iframework.support.spring.controller.BaseControllerSupport;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.lp.business.domain.Result;
import com.lp.business.model.Member;
import com.lp.business.service.MemberService;
import com.lp.business.wxpay.utils.weixin.PayUtil;
import com.lp.business.wxpay.utils.weixin.config.WxPayConfig;
import com.lp.service.function.BusinessUtil;

/**
 * 微信支付
 * @author lipeng
 *
 */
@RequestMapping("/weixin")
@RestController
public class WeixinController extends BaseControllerSupport{
	@Autowired
	private MemberService memberService;
	
    /**
     *  发起微信支付
     */
    @RequestMapping(value= "wxPay", method = { RequestMethod.POST, RequestMethod.GET })
    public Result wxPay(HttpServletRequest request, final HttpServletResponse response){
    	String openId = (String)request.getAttribute("openId");
		if(V.isEmpty(openId)) {
			return Result.error("非法的token");
		}
		Member member = memberService.findByOpenId(openId);
		if(V.isEmpty(member)) {
			return Result.error("非法的token");
		}
        try{
        	//1.组织请求参数到map中
        	String openid = member.getOpenId();
            //生成的随机字符串
            String nonce_str = BusinessUtil.getRandomString(32);
            String out_trade_no = "report20180921"+new Date().getTime();
            Map<String, String> params = new HashMap<String, String>();
            params.put("appid", WxPayConfig.appid);
            params.put("mch_id", WxPayConfig.mch_id);
            params.put("trade_type", WxPayConfig.TRADETYPE);
            params.put("notify_url", WxPayConfig.notify_url);
            params.put("body", "测试商品名称");
            params.put("openid", openid);
            params.put("nonce_str", nonce_str);
            params.put("out_trade_no", out_trade_no);//商户订单号
            params.put("total_fee", "1");//支付金额，单位：分，这边需要转成字符串类型，否则后面的签名会失败
            params.put("spbill_create_ip", this.getRemortIP(request));
            //2.基于请求参数map生成sign
            //2.1把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串,并加盐
            String prestr = PayUtil.createLinkStringWithKey(params); 
            //2.2MD5运算生成签名，这里是第一次签名，用于调用统一下单接口
            String sign = PayUtil.sign(prestr, "utf-8");
            L.i("=======================第一次签名：" + sign + "=====================");
            //2.3将签名参数放入参数map中，并将map转成xml格式的string
            params.put("sign", sign);
            //拼接统一下单接口使用的xml数据，要将上一步生成的签名一起拼接进去
            String xmlParmas = PayUtil.map2XmlString(params);
            //2.4调用统一下单接口，并接收返回的结果
            L.i("统一下单接口 请求XML数据：" + xmlParmas);
            String result = PayUtil.httpRequest(WxPayConfig.pay_url, "POST", xmlParmas);
            L.i("统一下单接口 返回XML数据：" + result);
            //2.5将返回的结果转储在HashMap中
            Map<String, String> map = PayUtil.xmlString2Map(result);
            //3.分析接口调用结果
            String return_code = map.get("return_code");//返回状态码
            //3.1如果成功，给前端返回需要的参数
            if(return_code == "SUCCESS" || return_code.equals(return_code)){
            	Map<String, String> data = new HashMap<String, String>();
            	data.put("appid", WxPayConfig.appid);
                String prepay_id = map.get("prepay_id");//返回的预付单信息
                data.put("nonce_str", nonce_str);
                data.put("package", "prepay_id=" + prepay_id);
                Long timeStamp = System.currentTimeMillis();
                data.put("timeStamp", timeStamp + "");//这边要将返回的时间戳转化成字符串，不然小程序端调用wx.requestPayment方法会报签名错误
                String stringSignTemp = "appId=" + WxPayConfig.appid + "&nonceStr=" + nonce_str + "&package=prepay_id=" + prepay_id+ "&signType=" + WxPayConfig.SIGNTYPE + "&timeStamp=" + timeStamp;
                //再次签名，这个签名用于小程序端调用wx.requesetPayment方法
                String paySign = PayUtil.sign(stringSignTemp, "utf-8");
                L.i("=======================第二次签名：" + paySign + "=====================");
                data.put("paySign", paySign);
                //更新订单信息
                //业务逻辑代码
                return Result.ok().put("data", data);
            }else{
            	return Result.error();
            }
        }catch(Exception e){
        	L.e(e.getMessage(), e);
			return Result.error("接口异常");
        }
    }

    /**
     * @Description:微信支付
     */
    @RequestMapping(value="/wxNotify")
    public void wxNotify(HttpServletRequest request,HttpServletResponse response){
    	try {
	        BufferedReader br = new BufferedReader(new InputStreamReader((ServletInputStream)request.getInputStream()));
	        String line = null;
	        StringBuilder sb = new StringBuilder();
			while((line = br.readLine())!=null){
			    sb.append(line);
			}
		
	        br.close();
	        //sb为微信返回的xml
	        String notityXml = sb.toString();
	        String resXml = "";
	        L.i("接收到的报文：" + notityXml);
	        // 将解析结果存储在HashMap中
	        Map<String, String> map = PayUtil.xmlString2Map(notityXml);
	        String returnCode = (String) map.get("return_code");
	        if("SUCCESS".equals(returnCode)){
	            //验证签名是否正确
	            if(PayUtil.verify(PayUtil.createLinkString(map), (String)map.get("sign"), WxPayConfig.key, "utf-8")){
	                /**此处添加自己的业务逻辑代码start**/
	                /**此处添加自己的业务逻辑代码end**/
	                //通知微信服务器已经支付成功
	                resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml> ";
	            }
	        }else{
	            resXml = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[报文为空]]></return_msg></xml> ";
	        }
	        L.i(resXml);
	        L.i("微信支付回调数据结束");
	
	        BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
	        out.write(resXml.getBytes());
	        out.close();
        } catch (IOException e) {
			e.printStackTrace();
		}
    }
}
